#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include"SnmpApi.h"
#include"SnmpClient.h"
#include"SnmpResultApi.h"
#include"PublicLog.h"
#ifndef NETSNMP_NO_WRITE_SUPPORT
#define NETSNMP_NO_WRITE_SUPPORT
#endif

#define SAFE_FREE_PDU(x)     do{if(x){snmp_free_pdu(x);x=NULL;}}while(0)

//错误使用过多时间
#define SNMP_ERR_USEMORETIME (MAX_SNMP_ERR+1)

#define MAX_GETBULK_NUM 100
#define MID_GETBULK_NUM 30
#define MIN_GETBULK_NUM 10

#define MAX_GET_NUM   50
#define MID_GET_NUM   35
#define MIN_GET_NUM   10

const char*GetPduNameByType(int GetType){
    static const char *StrGet="GET";
    static const char *StrGetNext="GETNEXT";
    static const char *StrGetBulk="GETBULK";
    static const char *StrUnKnow="未知";
    if(GetType==SNMP_MSG_GET){
		return StrGet;
    }else
    if(GetType==SNMP_MSG_GETNEXT){
		return StrGetNext;
    }else
    if(GetType==SNMP_MSG_GETBULK){
		return StrGetBulk;
    }
    return StrUnKnow;
}
static int bDebug=0;
const char*GetStatNameByType(int STATCODE){
    static const char *StrSuccess="成功";
    static const char *StrError="错误";
    static const char *StrTimeOut="超时";
    static const char *StrUnKnow="未知";
    if(STATCODE==STAT_SUCCESS){
		return StrSuccess;
    }else
    if(STATCODE==STAT_ERROR){
		return StrError;
    }else
    if(STATCODE==STAT_TIMEOUT){
		return StrTimeOut;
    }
    return StrUnKnow;
}
/*此处oidtype为限制bulk的发送数量*/
static const SnmpOidInfo g_checklist[]={
{"hwSpecial",{1,3,6,1,4,1,2011,5,25,31,1,1,2,1},14,MID_GETBULK_NUM},
{"h3cSpecial",{1,3,6,1,4,1,25506,2,70,1,1,1},12,MIN_GET_NUM},
{"RuijieSpecial",{1,3,6,1,4,1,4881,1,1,10,2,105,1,1,1},15,MIN_GET_NUM},
{"dot1dTpFdbStatus",{1,3,6,1,2,1,17,4,3,1,3},11,MID_GETBULK_NUM},
{"NULL",{0},0,ASN_NULL}
};
static const SnmpOidInfo g_checklistget[]={
{"CommonSpecial",{1,3,6,1,2,1,4,24,4},9,MID_GET_NUM},
{"NULL",{0},0,ASN_NULL}
};
netsnmp_pdu*CreatePdu(int GetType,netsnmp_variable_list*Check,int usemidnum){
    netsnmp_pdu*pdu=NULL;
    if(GetType==SNMP_MSG_GET){
		pdu = snmp_pdu_create(SNMP_MSG_GET);
    }else
    if(GetType==SNMP_MSG_GETNEXT){
		pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
    }else
    if(GetType==SNMP_MSG_GETBULK){
		pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
		pdu->non_repeaters=0;
		pdu->max_repetitions=MAX_GETBULK_NUM;
		if(usemidnum==2){
			pdu->max_repetitions=MIN_GETBULK_NUM;
		}else
		if(usemidnum==1){
			pdu->max_repetitions=MID_GETBULK_NUM;
		}else{
//当OID在为指定OID,将减少当次请求数量
			int i=0;
			while(g_checklist[i].oidLen>0){
				if(OID_COMPARE(g_checklist[i],Check)==0){
					pdu->max_repetitions=g_checklist[i].oidType;
					break;
                }
				i++;
            }
        }
    }
    return pdu;
}

netsnmp_variable_list*snmp_varlist_add_null_var(netsnmp_variable_list**varlist,const oid*name,size_t name_length){
    return snmp_varlist_add_variable(varlist,name,name_length,ASN_NULL,NULL,0);
}
void AddSnmpRequestByNull(netsnmp_variable_list**varlist,SnmpOidInfo OidInfo){
	snmp_varlist_add_variable(varlist,OidInfo.oidName,OidInfo.oidLen,ASN_NULL,NULL,0);
}
void AddSnmpRequestByNum(netsnmp_variable_list**varlist,SnmpOidInfo OidInfo,uint32_t num){
    OidInfo.oidName[OidInfo.oidLen++]=num;
    snmp_varlist_add_variable(varlist,OidInfo.oidName,OidInfo.oidLen,ASN_NULL,NULL,0);
}
static int sess_query(netsnmp_variable_list*list,int request,void*sessp,long&errstat,int usemidnum){
    netsnmp_pdu *pdu =CreatePdu(request,list,usemidnum);
    netsnmp_pdu *response = NULL;
    int SendNum=count_varbinds(list);
    int RecvNum=0;
//将请求OID赋值个第一个请求队列
//将list的链表给list
    errstat=SNMP_ERR_NOERROR;
    pdu->variables = SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
    snmp_clone_var(list,pdu->variables);
    pdu->variables->next_variable=list->next_variable;
    list->next_variable=NULL;
    int ret = snmp_sess_synch_response(sessp,pdu,&response);
    if(ret == STAT_SUCCESS){
//判断出问题的是否为'.1.3.6.1.4.1.4881.1.1.10.2.1.1.2.0'
		if(response->errstat==SNMP_ERR_NOSUCHNAME){
			int i=1;
			netsnmp_variable_list*tmp=response->variables;
			while(i<response->errindex){
				if(tmp){
					tmp=tmp->next_variable;
				}else{
					break;
                }
				i++;
            }
			static const char*CheckOid=".1.3.6.1.4.1.4881.1.1.10.2.1.1.2.0";
			char OidName[1024]={0};
			snprint_objid(OidName,sizeof(OidName),tmp->name,tmp->name_length);
			if(strncmp(OidName,CheckOid,strlen(CheckOid))==0){
				response->errstat=SNMP_ERR_NOERROR;
				response->errindex=0;
            }
        }
		if(response->errstat != SNMP_ERR_NOERROR){
			if(bDebug){
				DEBUG("IP:%s ret:%d errstat:%ld errindex:%ld Type:%s",
				GetSnmpPeerName(sessp),ret,response->errstat,response->errindex,GetPduNameByType(request));
				ShowSnmpVariable(response->variables);
            }
			errstat=response->errstat;
			SAFE_FREE_PDU(response);
			return STAT_ERROR;
		}else{
			SAFE_FREE_VARBIND(list->next_variable);
			snmp_clone_var(response->variables,list);
			list->next_variable=response->variables->next_variable;
			response->variables->next_variable=NULL;
			RecvNum=count_varbinds(list);
			if((request==SNMP_MSG_GET)&&(SendNum!=RecvNum)){
				WRONG("请求IP:%s 请求数量:%d 接收数量:%d 请求类型:%s",GetSnmpPeerName(sessp),SendNum,RecvNum,GetPduNameByType(request));
			}else{
				if(request!=SNMP_MSG_GETNEXT)
				DEBUG("请求IP:%s 请求数量:%d 接收数量:%d 请求类型:%s",GetSnmpPeerName(sessp),SendNum,RecvNum,GetPduNameByType(request));
            }
        }
    }else{
		DEBUG("请求IP:%s RET:%s 请求数量:%d 请求类型:%s",GetSnmpPeerName(sessp),GetStatNameByType(ret),SendNum,GetPduNameByType(request));
    }
    SAFE_FREE_PDU(response);
    return ret;
}
//构建请求队列，返回剩下位置
netsnmp_variable_list*make_snmp_requestlist(netsnmp_variable_list**request,netsnmp_variable_list*pos,int MaxRequestNum){
	int count=0;
	while((pos!=NULL)&&(count<MaxRequestNum)){
		snmp_varlist_add_null_var(request,pos->name,pos->name_length);
		count++;
		pos=pos->next_variable;
    }
	return pos;
}
int netsnmp_sess_query_get_ex(netsnmp_variable_list*list,void*sessp,int bAlarm){
    netsnmp_variable_list*pos=list;
    netsnmp_variable_list*res_list=NULL;//返回结果队列
    netsnmp_variable_list*last_list=NULL;//最后数据的指针
    int ret=SNMP_ERR_NOERROR;
    long errstat=SNMP_ERR_NOERROR;
//设置最大请求数
    int MaxRequestNum=MAX_GET_NUM;
//根据请求的OID设置最大请求数
    if(list==NULL)return ret;
    do{
		int i=0;
		while(g_checklistget[i].oidLen>0){
			if(OID_COMPARE(g_checklistget[i],list)==0){
				MaxRequestNum=g_checklistget[i].oidType;
				break;
			}
			i++;
		}
    }while(0);
    while((pos!=NULL)&&(ret==SNMP_ERR_NOERROR)){
		netsnmp_variable_list*request=NULL;
		pos=make_snmp_requestlist(&request,pos,MaxRequestNum);
		ret=sess_query(request,SNMP_MSG_GET,sessp,errstat,0);
		if(ret!=SNMP_ERR_NOERROR){
//如果因为请求数量过多,减少请求次数重试一次
#if 1
			if((errstat==SNMP_ERR_TOOBIG)&&(MaxRequestNum>MIN_GET_NUM)){
				pos=list;
				ret=SNMP_ERR_NOERROR;
				if(MaxRequestNum>MID_GET_NUM){
					MaxRequestNum=MID_GET_NUM;
				}else{
					MaxRequestNum=MIN_GET_NUM;
                }
				char OidName[1024]={0};
				snprint_objid(OidName,sizeof(OidName),list->name,list->name_length);
				DEBUG("IP:%s RET:%ld OID:%s 请求个数降低为:%d",GetSnmpPeerName(sessp),errstat,OidName,MaxRequestNum);
			}else
#endif
			if(bAlarm||bDebug){
				char OidName[1024]={0};
				netsnmp_session*sptr=snmp_sess_session(sessp);
				snprint_objid(OidName,sizeof(OidName),list->name,list->name_length);
				WRONG("IP:%s GET_EX STAT_ERROR:%d SysErr:%d SnmpErr:%d OID:%s",
				GetSnmpPeerName(sessp),ret,sptr->s_errno,sptr->s_snmp_errno,OidName);
            }
			if(errstat==SNMP_ERR_UNKNOWN)
				ret=SNMP_ERR_UNKNOWN;
      }else{
			if(res_list==NULL){
				if(request){
					res_list = SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
					snmp_clone_var(request,res_list);
					res_list->next_variable=request->next_variable;
					request->next_variable=NULL;
					last_list=res_list;
                }
			}else{
            if(request){
               last_list->next_variable=SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
               snmp_clone_var(request,last_list->next_variable);
               last_list->next_variable->next_variable=request->next_variable;
               request->next_variable=NULL;
            }
        }
        while(last_list->next_variable)
           last_list=last_list->next_variable;
        }
		SAFE_FREE_VARBIND(request);
    }
    if(res_list){
		SAFE_FREE_VARBIND(list->next_variable);
		snmp_clone_var(res_list,list);
		list->next_variable = res_list->next_variable;
		res_list->next_variable = NULL;
		SAFE_FREE_VARBIND(res_list);
    }
    return ret;
}

int CheckIsArpTable(oid*name,size_t name_length){
    char OidName[1024]={0};
    snprint_objid(OidName,sizeof(OidName),name,name_length);
//OID_ipNetToMediaPhysAddress
    if(strncmp(OidName,".1.3.6.1.2.1.4.22.1.2",21)==0){
		return 1;
    }
    return 0;
}
//检查是否有很多相同Arp数据
//0没有，1有
//匹配的物理地址，待检测的值，相同次数
int CheckMoreSameArpData(char*PhysAddress,netsnmp_variable_list*var,int&sametimes){
    char CheckPhysAddress[20]={0};
	static const SnmpOidInfo OID_ipNetToMediaPhysAddress={"ipNetToMediaPhysAddress",{1,3,6,1,2,1,4,22,1,2},10,ASN_OCTET_STR};
    if(ReadMacFromResult(var,OID_ipNetToMediaPhysAddress,CheckPhysAddress)==0){
		if(strcmp(CheckPhysAddress,PhysAddress)==0){
			sametimes++;
			if(sametimes>300){
				return 1;
            }
		}else{
			strcpy(PhysAddress,CheckPhysAddress);
			sametimes=0;
        }
    }
    return 0;
}
//检查所有队列都一致则进行报警
//在超时中使用
void CheckArpError(const char*IP,netsnmp_variable_list*list){
    char CheckPhysAddress[20]={0};
    int  bFirst=1;
    netsnmp_variable_list*var=list;
    while(var!=NULL){
		char ReadPhysAddress[20]={0};
		static const SnmpOidInfo OID_ipNetToMediaPhysAddress={"ipNetToMediaPhysAddress",{1,3,6,1,2,1,4,22,1,2},10,ASN_OCTET_STR};
		if(ReadMacFromResult(var,OID_ipNetToMediaPhysAddress,ReadPhysAddress)==0){
			if(bFirst){
				strcpy(CheckPhysAddress,ReadPhysAddress);
				bFirst=0;
			}else{
            if(strcmp(CheckPhysAddress,ReadPhysAddress)!=0)
               return;
            }
        }
		var=var->next_variable;
    }
    WRONG("Arp表错误:%s PhysAddress:%s",IP,CheckPhysAddress);
//  g_SwitchAlarmManager.AddConfigErrAlarm(IP);
}

int CheckIsRouteTable(oid*name,size_t name_length){
//非IDC跳过此判断
//都跳过非默认路由	
//  if(g_sysconf.checkidc==0)return 0;
    char OidName[1024]={0};
    snprint_objid(OidName,sizeof(OidName),name,name_length);
//OID_ipCidrRouteIfIndex
    if(strncmp(OidName,".1.3.6.1.2.1.4.24.4.1.5",23)==0){
		return 1;
    }else
//OID_ipRouteNextHop
    if(strncmp(OidName,".1.3.6.1.2.1.4.21.1.7",21)==0){
		return 1;
    }
    return 0;
}
//0默认路由，1非默认路由
int CheckIsDefaultRoute(netsnmp_variable_list*result){
    char OidName[1024]={0};
    char ipRouteDest[16]={0};
	char ipRouteMask[16]={0};
    snprint_objid(OidName,sizeof(OidName),result->name,result->name_length);
//OID_ipCidrRouteIfIndex
    if(strncmp(OidName,".1.3.6.1.2.1.4.24.4.1.5",23)==0){
		static const SnmpOidInfo OID_ipCidrRouteIfIndex={"ipCidrRouteIfIndex",{1,3,6,1,2,1,4,24,4,1,5},11,ASN_INTEGER};
		int rootlen=OID_ipCidrRouteIfIndex.oidLen;
		OidReadIP(result->name,rootlen+0,ipRouteDest);
		OidReadIP(result->name,rootlen+4,ipRouteMask);
    }else
//OID_ipRouteNextHop
    if(strncmp(OidName,".1.3.6.1.2.1.4.21.1.7",21)==0){
		static const SnmpOidInfo OID_ipRouteNextHop={"ipRouteNextHop",{1,3,6,1,2,1,4,21,1,7},10,ASN_IPADDRESS};
		int rootlen=OID_ipRouteNextHop.oidLen;
		OidReadIP(result->name,rootlen+0,ipRouteDest);
    }
    if(strcmp(ipRouteDest,"0.0.0.0")!=0){
//本地lo路由忽略		
		if(strcmp(ipRouteMask,"255.255.255.255")==0){
			return 0;
		}
		return 1;
	}
    return 0;
}
#if 0
int _netsnmp_sess_query_walkbulk(netsnmp_variable_list*list,void*sessp,int MaxWaitTime){
	netsnmp_variable_list *vb = snmp_clone_varbind(list);
	netsnmp_variable_list *res_list = NULL;//存储结果
	netsnmp_variable_list *last_list = NULL;//存储结果
	int  ret = 0;
	int  bArpTable=0;//判断是否是Arp表
	int  bRouteTable=0;//判断是否获取路由表
	int  samenum=0;//重复数量
	long errstat=SNMP_ERR_NOERROR;
	char PhysAddress[20]="00:00:00:00:00:00";
	time_t timestamp=time(NULL);
	int useminbulk=0;
	bArpTable=CheckIsArpTable(list->name,list->name_length);
	bRouteTable=CheckIsRouteTable(list->name,list->name_length);
	//WARN("bArpTable:%d bRouteTable:%d",bArpTable,bRouteTable);
	ret = sess_query(vb, SNMP_MSG_GETBULK,sessp,errstat,useminbulk);
	while (ret == SNMP_ERR_NOERROR){
		netsnmp_variable_list*pos=vb;
		netsnmp_variable_list*newvb=NULL;
//预先判断
		if(count_varbinds(vb)==1&&vb->type==ASN_NULL){
			pos=NULL;
			useminbulk++;
			if(useminbulk<3){
				snmp_varlist_add_variable(&newvb,vb->name,vb->name_length,ASN_NULL,NULL,0);
            }
        }

		while(pos!=NULL){
			if (pos->type == SNMP_ENDOFMIBVIEW ||
			    pos->type == SNMP_NOSUCHOBJECT ||
			    pos->type == SNMP_NOSUCHINSTANCE){
			    SAFE_FREE_VARBIND(newvb);
				break;
			}else{
				if(snmp_oidtree_compare(list->name,list->name_length,pos->name,pos->name_length)==0){
//////////////////////////////////////////////////////////
					if(bArpTable){
						if(CheckMoreSameArpData(PhysAddress,pos,samenum)==1){
							SAFE_FREE_VARBIND(newvb);
							WRONG("Arp表错误:%s PhysAddress:%s",GetSnmpPeerName(sessp),PhysAddress);
							//g_SwitchAlarmManager.AddConfigErrAlarm(GetSnmpPeerName(sessp));
							break;
						}
					}else
					if(bRouteTable){
						if(CheckIsDefaultRoute(pos)==1){
							SAFE_FREE_VARBIND(newvb);
							WRONG("碰到非默认路由跳过:%s ",GetSnmpPeerName(sessp));;
							break;
						}
					}
/////////////////////////////////////////////////////////
					if(res_list==NULL){
						res_list=SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
						last_list=res_list;
					}else{
						last_list->next_variable=SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
						last_list=last_list->next_variable;
				    }
					if(newvb==NULL){
						snmp_varlist_add_variable(&newvb,pos->name,pos->name_length,ASN_NULL,NULL,0);
					}else{
						snmp_set_var_objid(newvb,pos->name,pos->name_length);
				    }
					snmp_clone_var(pos,last_list);
				}else{
					SAFE_FREE_VARBIND(newvb);
					break;
				}
			}
			pos=pos->next_variable;
		}
//不管结果如何都要释放结果集
		snmp_free_varbind(vb);
		vb=newvb;
		if(vb!=NULL){
			if((time(NULL)-timestamp)<MaxWaitTime){
				ret = sess_query(vb,SNMP_MSG_GETBULK,sessp,errstat,useminbulk);
			}else{
				char OidName[1024]={0};
				snprint_objid(OidName,sizeof(OidName),list->name,list->name_length);
				WRONG("IP:%s OID:%s 数据采集时间超过(%d)s netsnmp_sess_query_walkbulk",GetSnmpPeerName(sessp),OidName,MaxWaitTime);
				if(bArpTable){
					CheckArpError(GetSnmpPeerName(sessp),res_list);
		        }
				ret=SNMP_ERR_USEMORETIME;
				break;
			}
		}else{
			break;
		}
	}
	if(res_list){
		SAFE_FREE_VARBIND(list->next_variable);
		snmp_clone_var(res_list, list);
		list->next_variable = res_list->next_variable;
		res_list->next_variable = NULL;
		SAFE_FREE_VARBIND(res_list);
	}else{
		if(ret==SNMP_ERR_NOERROR)
			ret=SNMP_NOSUCHINSTANCE;
	}
	SAFE_FREE_VARBIND(vb);
	return ret;
}
int _netsnmp_sess_query_walk(netsnmp_variable_list*list,void*sessp,int MaxWaitTime){
    netsnmp_variable_list *vb = snmp_clone_varbind(list);//每次需要获取的变量
    netsnmp_variable_list *res_list = NULL;//存储结果
    netsnmp_variable_list *last_list = NULL;//存储结果
    int  ret = 0;
    long errstat=SNMP_ERR_NOERROR;
    int  bArpTable=0;//判断是否是Arp表
    int  bRouteTable=0;//判断是否获取路由表
    int  samenum=0;//重复数量
    char PhysAddress[20]="00:00:00:00:00:00";
    time_t timestamp=time(NULL);
    bArpTable=CheckIsArpTable(list->name,list->name_length);
    bRouteTable=CheckIsRouteTable(list->name,list->name_length);
    ret = sess_query(vb,SNMP_MSG_GETNEXT,sessp,errstat,0);
    while(ret == SNMP_ERR_NOERROR){
		netsnmp_variable_list*pos=vb;
		if(pos!=NULL){
			if(pos->type == SNMP_ENDOFMIBVIEW ||
				pos->type == SNMP_NOSUCHOBJECT ||
				pos->type == SNMP_NOSUCHINSTANCE){
				SAFE_FREE_VARBIND(vb);
				break;
			}else
			if(snmp_oidtree_compare(list->name,list->name_length,pos->name,pos->name_length)==0){
				if(bArpTable){
					if(CheckMoreSameArpData(PhysAddress,pos,samenum)==1){
						SAFE_FREE_VARBIND(vb);
						WRONG("Arp表错误:%s PhysAddress:%s",GetSnmpPeerName(sessp),PhysAddress);
						//g_SwitchAlarmManager.AddConfigErrAlarm(GetSnmpPeerName(sessp));
						break;
					}
				}else
				if(bRouteTable){
					if(CheckIsDefaultRoute(pos)==1){
						SAFE_FREE_VARBIND(vb);
						WRONG("碰到非默认路由跳过:%s ",GetSnmpPeerName(sessp));;
						break;
					}
                }
				if(res_list==NULL){
					res_list=SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
					last_list=res_list;
				}else{
					last_list->next_variable=SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
					last_list=last_list->next_variable;
                }
				snmp_clone_var(pos,last_list);
				snmp_set_var_typed_value(vb,ASN_NULL,pos->name,pos->name_length);
			}else{
				SAFE_FREE_VARBIND(vb);
            }
        }
		if(vb!=NULL){
			if((time(NULL)-timestamp)<MaxWaitTime){
				ret = sess_query(vb,SNMP_MSG_GETNEXT,sessp,errstat,0);
			}else{
				char OidName[1024]={0};
				snprint_objid(OidName,sizeof(OidName),list->name,list->name_length);
				WRONG("IP:%s OID:%s 数据采集时间超过(%d)s netsnmp_sess_query_walk",GetSnmpPeerName(sessp),OidName,MaxWaitTime);
				if(bArpTable){
					CheckArpError(GetSnmpPeerName(sessp),res_list);
                }
				ret=SNMP_ERR_USEMORETIME;
				break;
			}
		}else{
			break;
        }
    }
//释放掉list后面的值
//把res_list第一个值给list,释放res_list第一个值
    if(res_list){
		SAFE_FREE_VARBIND(list->next_variable);
		snmp_clone_var(res_list, list);
		list->next_variable = res_list->next_variable;
		res_list->next_variable = NULL;
		SAFE_FREE_VARBIND(res_list);
    }else{
		if(ret==SNMP_ERR_NOERROR)
			ret=SNMP_NOSUCHINSTANCE;
    }
    SAFE_FREE_VARBIND(vb);
    return ret;
}
netsnmp_variable_list*netsnmp_sess_query_walkall(void*sessp,SnmpOidInfo oid,int bAlarm,int bPassWalkBulk,int MaxWaitTime){
    if(sessp==NULL)return NULL;
	if(bPassWalkBulk==0){
		do{
			netsnmp_variable_list*result=NULL;
			snmp_varlist_add_variable(&result,oid.oidName,oid.oidLen,ASN_NULL,NULL,0);
			int Ret=_netsnmp_sess_query_walkbulk(result,sessp,MaxWaitTime);
			if(Ret==SNMP_ERR_NOERROR){
				return result;
			}else
			if(Ret==SNMP_NOSUCHINSTANCE){
				if(bAlarm||bDebug){
					WRONG("IP[%s]没有该OID %s 信息(bulkwalk)",GetSnmpPeerName(sessp),oid.strName);
				}
				snmp_free_varbind(result);
				return NULL;
			}else{
				DEBUG("IP[%s]使用snmpbulkwalk方式采集%s失败 %d",GetSnmpPeerName(sessp),oid.strName,Ret);
				snmp_free_varbind(result);
			}
		}while(0);
	}
//bulk放式获取失败使用get方式
    do{
		netsnmp_variable_list*result=NULL;
		snmp_varlist_add_variable(&result,oid.oidName,oid.oidLen,ASN_NULL,NULL,0);
		int Ret=_netsnmp_sess_query_walk(result,sessp,MaxWaitTime);
		if(Ret==SNMP_ERR_NOERROR){
			if(bPassWalkBulk==0)
			INFOEX("IP[%s]采集%s需要使用walk方式",GetSnmpPeerName(sessp),oid.strName);
			return result;
		}else
		if(Ret==SNMP_NOSUCHINSTANCE){
			if(bAlarm||bDebug){
				WRONG("IP[%s]没有该OID %s 信息(walk)",GetSnmpPeerName(sessp),oid.strName);
            }
			snmp_free_varbind(result);
			return NULL;
		}else{
			char OidName[1024]={0};
			snprint_objid(OidName,sizeof(OidName),oid.oidName,oid.oidLen);
			WRONG("IP[%s]使用snmpwalk方式采集%s(%s)失败 %d",GetSnmpPeerName(sessp),oid.strName,OidName,Ret);
			snmp_free_varbind(result);
        }
    }while(0);
    return NULL;
}
#else
netsnmp_variable_list*netsnmp_sess_query_walkall(void*sessp,SnmpOidInfo oid,int bAlarm,int bPassWalkBulk,int MaxWaitTime){
	return netsnmp_sess_query_walkallex(sessp,oid,oid,bAlarm,bPassWalkBulk,MaxWaitTime);
}
#endif

int _netsnmp_sess_query_walkbulkex(netsnmp_variable_list*list,void*sessp,SnmpOidInfo startoid,SnmpOidInfo endoid,int gettype,int MaxWaitTime){
	netsnmp_variable_list *vb = snmp_clone_varbind(list);
	netsnmp_variable_list *res_list = NULL;//存储结果
	netsnmp_variable_list *last_list = NULL;//存储结果
	int  ret = 0;
	int  bArpTable=0;//判断是否是Arp表
	int  bRouteTable=0;//判断是否获取路由表
	int  samenum=0;//重复数量
	long errstat=SNMP_ERR_NOERROR;
	char PhysAddress[20]="00:00:00:00:00:00";
	time_t timestamp=time(NULL);
	int useminbulk=0;
	//非GETBULK方式 没有重试机会
	if(gettype!=SNMP_MSG_GETBULK){
		useminbulk=4;
	}
	bArpTable=CheckIsArpTable(list->name,list->name_length);
	bRouteTable=CheckIsRouteTable(list->name,list->name_length);
	ret = sess_query(vb, gettype,sessp,errstat,useminbulk);
	while (ret == SNMP_ERR_NOERROR){
		netsnmp_variable_list*pos=vb;
		netsnmp_variable_list*newvb=NULL;
//预先判断
//多半请求量过多不支持		
//判断是否有数据返回		
		if(count_varbinds(vb)==1&&vb->type==ASN_NULL){
			pos=NULL;
			useminbulk++;
			if(useminbulk<3){
				snmp_varlist_add_variable(&newvb,vb->name,vb->name_length,ASN_NULL,NULL,0);
            }
        }

		while(pos!=NULL){
			if (pos->type == SNMP_ENDOFMIBVIEW || pos->type == SNMP_NOSUCHOBJECT || pos->type == SNMP_NOSUCHINSTANCE){
			    SAFE_FREE_VARBIND(newvb);
				break;
			}else{
				if(snmp_oidtree_compare(startoid.oidName,startoid.oidLen,pos->name,pos->name_length)<=0&&
				   snmp_oidtree_compare(endoid.oidName,endoid.oidLen,pos->name,pos->name_length)>=0)
				{
//////////////////////////////////////////////////////////
					if(bArpTable){
						if(CheckMoreSameArpData(PhysAddress,pos,samenum)==1){
							SAFE_FREE_VARBIND(newvb);
							WRONG("Arp表错误:%s PhysAddress:%s",GetSnmpPeerName(sessp),PhysAddress);
							//g_SwitchAlarmManager.AddConfigErrAlarm(GetSnmpPeerName(sessp));
							break;
						}
					}else
					if(bRouteTable){
						if(CheckIsDefaultRoute(pos)==1){
							SAFE_FREE_VARBIND(newvb);
							WRONG("碰到非默认路由跳过:%s ",GetSnmpPeerName(sessp));;
							break;
						}
					}
/////////////////////////////////////////////////////////
					if(res_list==NULL){
						res_list=SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
						last_list=res_list;
					}else{
						last_list->next_variable=SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
						last_list=last_list->next_variable;
				    }
					if(newvb==NULL){
						snmp_varlist_add_variable(&newvb,pos->name,pos->name_length,ASN_NULL,NULL,0);
					}else{
						snmp_set_var_objid(newvb,pos->name,pos->name_length);
				    }
					snmp_clone_var(pos,last_list);
				}else{
					SAFE_FREE_VARBIND(newvb);
					break;
				}
			}
			pos=pos->next_variable;
		}
//不管结果如何都要释放结果集
		SAFE_FREE_VARBIND(vb);
		vb=newvb;
		if(vb!=NULL){
			if((time(NULL)-timestamp)<MaxWaitTime){
				ret = sess_query(vb,gettype,sessp,errstat,useminbulk);
			}else{
				char OidName[1024]={0};
				snprint_objid(OidName,sizeof(OidName),list->name,list->name_length);
				WRONG("IP:%s OID:%s 数据采集时间超过(%d)s netsnmp_sess_query_walkbulk",GetSnmpPeerName(sessp),OidName,MaxWaitTime);
				if(bArpTable){
					CheckArpError(GetSnmpPeerName(sessp),res_list);
		        }
				ret=SNMP_ERR_USEMORETIME;
				break;
			}
		}else{
			break;
		}
	}
	if(res_list){
		SAFE_FREE_VARBIND(list->next_variable);
		snmp_clone_var(res_list, list);
		list->next_variable = res_list->next_variable;
		res_list->next_variable = NULL;
		SAFE_FREE_VARBIND(res_list);
	}else{
		if(ret==SNMP_ERR_NOERROR){
			ret=SNMP_NOSUCHINSTANCE;
		}
	}
	SAFE_FREE_VARBIND(vb);
	return ret;
}

netsnmp_variable_list*netsnmp_sess_query_walkallex(void*sessp,SnmpOidInfo startoid,SnmpOidInfo endoid,int bAlarm,int bPassWalkBulk,int MaxWaitTime){
	if(sessp==NULL)return NULL;
	if(bPassWalkBulk==0){
		do{
			netsnmp_variable_list*result=NULL;
			AddSnmpRequestByNull(&result,startoid);
			int Ret=_netsnmp_sess_query_walkbulkex(result,sessp,startoid,endoid,SNMP_MSG_GETBULK,MaxWaitTime);
			if(Ret==SNMP_ERR_NOERROR){
				return result;
			}else
			if(Ret==SNMP_NOSUCHINSTANCE){
				if(bAlarm||bDebug){
					WRONG("IP[%s]没有该OID %s 信息(bulkwalk)",GetSnmpPeerName(sessp),startoid.strName);
				}
				snmp_free_varbind(result);
				return NULL;
			}else{
				DEBUG("IP[%s]使用snmpbulkwalk方式采集%s失败 %d",GetSnmpPeerName(sessp),startoid.strName,Ret);
				snmp_free_varbind(result);
			}
		}while(0);
	}
	do{
		netsnmp_variable_list*result=NULL;
		AddSnmpRequestByNull(&result,startoid);
		int Ret=_netsnmp_sess_query_walkbulkex(result,sessp,startoid,endoid,SNMP_MSG_GETNEXT,MaxWaitTime);
		if(Ret==SNMP_ERR_NOERROR){
			return result;
		}else
		if(Ret==SNMP_NOSUCHINSTANCE){
			if(bAlarm||bDebug){
				WRONG("IP[%s]没有该OID %s 信息(bulkwalk)",GetSnmpPeerName(sessp),startoid.strName);
            }
			snmp_free_varbind(result);
			return NULL;
		}else{
			DEBUG("IP[%s]使用snmpbulkwalk方式采集%s失败 %d",GetSnmpPeerName(sessp),startoid.strName,Ret);
			snmp_free_varbind(result);
        }
    }while(0);
	return NULL;
}


